package com.ld.shieldsb.es.model.search;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.ScoreSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;

import com.ld.shieldsb.common.core.reflect.FunctionUtil.Property;
import com.ld.shieldsb.common.core.util.StringUtils;
import com.ld.shieldsb.dao.model.QueryManager;
import com.ld.shieldsb.es.model.search.Condition.LinkType;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

@Data
@Slf4j
public class ElasticSearchQueryModel implements Cloneable {

    protected String includeFields = "*"; // 返回字段
    protected String excludeFields = null; // 排除字段

    protected String highlightFieldName = ""; // 高亮字段

    protected List<MultiCondition> cnds = new ArrayList<>(); // 条件
//    protected List<Condition> cnds = new ArrayList<>(); // 条件
    protected List<Order> orders = new ArrayList<>(); // 排序

    public ElasticSearchQueryModel() {
        cnds.add(new MultiCondition());
    }

    public ElasticSearchQueryModel(String selectFields) {
        this.includeFields = selectFields;
        cnds.add(new MultiCondition());
    }

    public ElasticSearchQueryModel(String fieldName, Object value) {
        andEq(fieldName, value);
    }

    /**
     * 获取主查询条件
     * 
     * @Title getMainCondition
     * @author 吕凯
     * @date 2020年8月18日 下午3:57:11
     * @return MultiCondition
     */
    public MultiCondition getMainCondition() {
        return cnds.get(0);
    }

    public ElasticSearchQueryModel andEq(String fieldName, Object value) {
        getMainCondition().andEq(fieldName, value);
        return this;
    }

    public <T> ElasticSearchQueryModel andEq(Property<T, ?> property, Object value) {
        getMainCondition().andEq(property, value);
        return this;
    }

    public ElasticSearchQueryModel andEq(String fieldName, Object value, Float boost) {
        getMainCondition().andEq(fieldName, value, boost);
        return this;
    }

    public <T> ElasticSearchQueryModel andEq(Property<T, ?> property, Object value, Float boost) {
        getMainCondition().andEq(property, value, boost);
        return this;
    }

    public ElasticSearchQueryModel orEq(String fieldName, Object value) {
        getMainCondition().orEq(fieldName, value);
        return this;
    }

    public <T> ElasticSearchQueryModel orEq(Property<T, ?> property, Object value) {
        getMainCondition().orEq(property, value);
        return this;
    }

    public ElasticSearchQueryModel orEq(String fieldName, Object value, Float boost) {
        getMainCondition().orEq(fieldName, value, boost);
        return this;
    }

    public <T> ElasticSearchQueryModel orEq(Property<T, ?> property, Object value, Float boost) {
        getMainCondition().orEq(property, value, boost);
        return this;
    }

    // 添加分词
    public ElasticSearchQueryModel andAnalysis(String fieldName, String value, String otherFieldNames) {
        getMainCondition().andAnalysis(fieldName, value, otherFieldNames);
        return this;
    }

    public ElasticSearchQueryModel andAnalysis(String fieldName, String value) {
        getMainCondition().andAnalysis(fieldName, value);
        return this;
    }

    /**
     * 分词查询多字段
     * 
     * @Title andAnalysis
     * @author 吕凯
     * @date 2020年8月18日 下午3:26:43
     * @param <T>
     * @param property
     * @param value
     * @param otherFieldNames
     *            其他查询字段，用逗号分隔
     * @return ElasticSearchQueryModel
     */
    public <T> ElasticSearchQueryModel andAnalysis(Property<T, ?> property, String value, String otherFieldNames) {
        getMainCondition().andAnalysis(property, value, otherFieldNames);
        return this;
    }

    public <T> ElasticSearchQueryModel andAnalysis(Property<T, ?> property, String value) {
        getMainCondition().andAnalysis(property, value);
        return this;
    }

    public ElasticSearchQueryModel andAnalysis(String fieldName, String value, String otherFieldNames, Float boost) {
        getMainCondition().andAnalysis(fieldName, value, otherFieldNames, boost);
        return this;
    }

    public ElasticSearchQueryModel andAnalysis(String fieldName, String value, Float boost) {
        getMainCondition().andAnalysis(fieldName, value, boost);
        return this;
    }

    /**
     * 分词查询多字段
     * 
     * @Title andAnalysis
     * @author 吕凯
     * @date 2020年8月18日 下午3:26:43
     * @param <T>
     * @param property
     * @param value
     * @param otherFieldNames
     *            其他查询字段，用逗号分隔
     * @return MultiCondition
     */
    public <T> ElasticSearchQueryModel andAnalysis(Property<T, ?> property, String value, String otherFieldNames, Float boost) {
        getMainCondition().andAnalysis(property, value, otherFieldNames, boost);
        return this;
    }

    public <T> ElasticSearchQueryModel andAnalysis(Property<T, ?> property, String value, Float boost) {
        getMainCondition().andAnalysis(property, value, boost);
        return this;
    }

    public ElasticSearchQueryModel orAnalysis(String fieldName, String value, String otherFieldNames) {
        getMainCondition().orAnalysis(fieldName, value, otherFieldNames);
        return this;
    }

    public ElasticSearchQueryModel orAnalysis(String fieldName, String value) {
        getMainCondition().orAnalysis(fieldName, value);
        return this;
    }

    /**
     * 分词查询多字段
     * 
     * @Title orAnalysis
     * @author 吕凯
     * @date 2020年8月18日 下午3:26:43
     * @param <T>
     * @param property
     * @param value
     * @param otherFieldNames
     *            其他查询字段，用逗号分隔
     * @return ElasticSearchQueryModel
     */
    public <T> ElasticSearchQueryModel orAnalysis(Property<T, ?> property, String value, String otherFieldNames) {
        getMainCondition().orAnalysis(property, value, otherFieldNames);
        return this;
    }

    public <T> ElasticSearchQueryModel orAnalysis(Property<T, ?> property, String value) {
        getMainCondition().orAnalysis(property, value);
        return this;
    }

    public ElasticSearchQueryModel orAnalysis(String fieldName, String value, String otherFieldNames, Float boost) {
        getMainCondition().orAnalysis(fieldName, value, otherFieldNames, boost);
        return this;
    }

    public ElasticSearchQueryModel orAnalysis(String fieldName, String value, Float boost) {
        getMainCondition().orAnalysis(fieldName, value, boost);
        return this;
    }

    /**
     * 分词查询多字段
     * 
     * @Title orAnalysis
     * @author 吕凯
     * @date 2020年8月18日 下午3:26:43
     * @param <T>
     * @param property
     * @param value
     * @param otherFieldNames
     *            其他查询字段，用逗号分隔
     * @return MultiCondition
     */
    public <T> ElasticSearchQueryModel orAnalysis(Property<T, ?> property, String value, String otherFieldNames, Float boost) {
        getMainCondition().orAnalysis(property, value, otherFieldNames, boost);
        return this;
    }

    public <T> ElasticSearchQueryModel orAnalysis(Property<T, ?> property, String value, Float boost) {
        getMainCondition().orAnalysis(property, value, boost);
        return this;
    }

    // unEQ
    public ElasticSearchQueryModel andUnEq(String fieldName, Object value, Float boost) {
        getMainCondition().andUnEq(fieldName, value, boost);
        return this;
    }

    public <T> ElasticSearchQueryModel andUnEq(Property<T, ?> property, Object value, Float boost) {
        getMainCondition().andUnEq(property, value, boost);
        return this;
    }

    public ElasticSearchQueryModel andUnEq(String fieldName, Object value) {
        getMainCondition().andUnEq(fieldName, value);
        return this;
    }

    public <T> ElasticSearchQueryModel andUnEq(Property<T, ?> property, Object value) {
        getMainCondition().andUnEq(property, value);
        return this;
    }

    // 大于
    public ElasticSearchQueryModel andGt(String fieldName, Object value) {
        getMainCondition().andGt(fieldName, value);
        return this;
    }

    public <T> ElasticSearchQueryModel andGt(Property<T, ?> property, Object value) {
        getMainCondition().andGt(property, value);
        return this;
    }

    public ElasticSearchQueryModel andGe(String fieldName, Object value) {
        getMainCondition().andGe(fieldName, value);
        return this;
    }

    public <T> ElasticSearchQueryModel andGe(Property<T, ?> property, Object value) {
        getMainCondition().andGe(property, value);
        return this;
    }

    // 小于
    public ElasticSearchQueryModel andLt(String fieldName, Object value) {
        getMainCondition().andLt(fieldName, value);
        return this;
    }

    public <T> ElasticSearchQueryModel andLt(Property<T, ?> property, Object value) {
        getMainCondition().andLt(property, value);
        return this;
    }

    public ElasticSearchQueryModel andLe(String fieldName, Object value) {
        getMainCondition().andLe(fieldName, value);
        return this;
    }

    public <T> ElasticSearchQueryModel andLe(Property<T, ?> property, Object value) {
        getMainCondition().andLe(property, value);
        return this;
    }

    public ElasticSearchQueryModel andLeftLike(String fieldName, String value) {
        getMainCondition().andLeftLike(fieldName, value);
        return this;
    }

    public <T> ElasticSearchQueryModel andLeftLike(Property<T, ?> property, String value) {
        getMainCondition().andLeftLike(property, value);
        return this;
    }

    public ElasticSearchQueryModel andRightLike(String fieldName, String value) {
        getMainCondition().andRightLike(fieldName, value);
        return this;
    }

    public <T> ElasticSearchQueryModel andRightLike(Property<T, ?> property, String value) {
        getMainCondition().andRightLike(property, value);
        return this;
    }

    public ElasticSearchQueryModel andLike(String fieldName, String value) {
        getMainCondition().andLike(fieldName, value);
        return this;
    }

    public <T> ElasticSearchQueryModel andLike(Property<T, ?> property, String value) {
        getMainCondition().andLike(property, value);
        return this;
    }

    // 范围
    /**
     * 
     * 范围搜索
     * 
     * @Title andRange
     * @author 吕凯
     * @date 2020年9月17日 下午4:43:27
     * @param fieldName
     * @param value1
     * @param value2
     * @param boost
     *            搜索权重
     * @return ElasticSearchQueryModel
     */
    public ElasticSearchQueryModel andRange(String fieldName, Object value1, Object value2, Float boost) {
        getMainCondition().andRange(fieldName, value1, value2, boost);
        return this;
    }

    public <T> ElasticSearchQueryModel andRange(Property<T, ?> property, Object value1, Object value2, Float boost) {
        getMainCondition().andRange(property, value1, value2, boost);
        return this;
    }

    public ElasticSearchQueryModel andRange(String fieldName, Object value1, Object value2) {
        getMainCondition().andRange(fieldName, value1, value2);
        return this;
    }

    public <T> ElasticSearchQueryModel andRegion(Property<T, ?> property, Object value1, Object value2) {
        getMainCondition().andRange(property, value1, value2);
        return this;
    }

    // set类型
    public ElasticSearchQueryModel andInSet(String fieldName, Object[] values) {
        getMainCondition().andInSet(fieldName, values);
        return this;
    }

    public <T> ElasticSearchQueryModel andInSet(Property<T, ?> property, Object[] values) {
        getMainCondition().andInSet(property, values);
        return this;
    }

    public <T> ElasticSearchQueryModel andInSet(Property<T, ?> property, Set<?> values) {
        getMainCondition().andInSet(property, values);
        return this;
    }

    public ElasticSearchQueryModel andInSet(String fieldName, Set<?> values) {
        getMainCondition().andInSet(fieldName, values);
        return this;
    }

    public ElasticSearchQueryModel orInSet(String fieldName, Object[] values) {
        getMainCondition().orInSet(fieldName, values);
        return this;
    }

    public <T> ElasticSearchQueryModel orInSet(Property<T, ?> property, Object[] values) {
        getMainCondition().orInSet(property, values);
        return this;
    }

    public <T> ElasticSearchQueryModel orInSet(Property<T, ?> property, Set<?> values) {
        getMainCondition().orInSet(property, values);
        return this;
    }

    public ElasticSearchQueryModel orInSet(String fieldName, Set<?> values) {
        getMainCondition().orInSet(fieldName, values);
        return this;
    }

    /**
     * 设置排序规则，如果之前设置过，该方法会重置，如果要追加使用addOrder方法
     * 
     * @Title setOrder
     * @author 吕凯
     * @date 2020年6月5日 下午6:13:58
     * @param fieldName
     * @param isDesc
     *            void
     */
    public ElasticSearchQueryModel setOrder(String fieldName, boolean isDesc, Object missing) {
        orders.clear();
        return addOrder(fieldName, isDesc, missing, null);
    }

    /**
     * 追加排序规则
     * 
     * @Title addOrder
     * @author 吕凯
     * @date 2020年6月2日 下午4:21:48
     * @param fieldName
     *            字段名称
     * @param isDesc
     *            是否倒序
     * @param missing
     *            缺失的默认值 void
     */
    public ElasticSearchQueryModel addOrder(String fieldName, boolean isDesc, Object missing, Integer index) {
        if (fieldName.contains(",")) {
            log.error("检测到排序字段名中使用了多个字符串，请使用setOrder设置主排序字段addOrder增加副排序字段");
        } else {
            Order order = new Order(fieldName, isDesc, missing);
            if (index != null) {
                orders.add(index, order);
            } else {
                orders.add(order);
            }
        }
        return this;
    }

    public <T> ElasticSearchQueryModel addOrder(Property<T, ?> property, boolean isDesc, Object missing) {
        return addOrder(QueryManager.getFunctionName(property), isDesc, missing, null);
    }

    public <T> ElasticSearchQueryModel addOrder(Property<T, ?> property, boolean isDesc) {
        return addOrder(property, isDesc, null);
    }

    /**
     * 将排序字段插入指定位置
     * 
     * @Title insertOrder
     * @author 吕凯
     * @date 2020年8月18日 下午4:24:26
     * @param <T>
     * @param property
     * @param isDesc
     * @param missing
     * @return ElasticSearchQueryModel
     */
    public <T> ElasticSearchQueryModel insertOrder(Property<T, ?> property, boolean isDesc, Object missing, int index) {
        return insertOrder(QueryManager.getFunctionName(property), isDesc, missing, index);
    }

    public <T> ElasticSearchQueryModel insertOrder(Property<T, ?> property, boolean isDesc, int index) {
        return insertOrder(property, isDesc, null, index);
    }

    public <T> ElasticSearchQueryModel insertOrder(String fieldName, boolean isDesc, Object missing, int index) {
        return addOrder(fieldName, isDesc, missing, index);
    }

    /**
     * 插入到第一个排序
     * 
     * @Title unshiftOrder
     * @author 吕凯
     * @date 2020年8月18日 下午4:30:09
     * @param <T>
     * @param property
     * @param isDesc
     * @param index
     * @return ElasticSearchQueryModel
     */
    public <T> ElasticSearchQueryModel unshiftOrder(Property<T, ?> property, boolean isDesc) {
        return unshiftOrder(property, isDesc, null);
    }

    public <T> ElasticSearchQueryModel unshiftOrder(Property<T, ?> property, boolean isDesc, Object missing) {
        return unshiftOrder(QueryManager.getFunctionName(property), isDesc, missing);
    }

    public ElasticSearchQueryModel unshiftOrder(String fieldName, boolean isDesc, Object missing) {
        return insertOrder(fieldName, isDesc, missing, 0);
    }

    public ElasticSearchQueryModel unshiftOrder(String fieldName, boolean isDesc) {
        return unshiftOrder(fieldName, isDesc, null);
    }

    public <T> ElasticSearchQueryModel setOrder(Property<T, ?> property, boolean isDesc, Object missing) {
        return setOrder(QueryManager.getFunctionName(property), isDesc, missing);
    }

    public <T> ElasticSearchQueryModel setOrder(Property<T, ?> property, boolean isDesc) {
        return setOrder(QueryManager.getFunctionName(property), isDesc, null);
    }

    public SearchSourceBuilder getOrder(SearchSourceBuilder searchBuilder) {
        for (Order order : orders) {
            Object missingObj = order.getMissing();
            if (Order.SCORE_SORT.equals(order.getColumn())) { // 得分
                searchBuilder.sort(new ScoreSortBuilder());
            } else {

                if (missingObj != null) {
                    FieldSortBuilder fieldsort = SortBuilders.fieldSort(order.getColumn()).missing(missingObj)
                            // .unmappedType("date")
                            .order(order.getIsDesc() ? SortOrder.DESC : SortOrder.ASC);
                    searchBuilder.sort(fieldsort);
                } else {
                    searchBuilder.sort(order.getColumn(), order.getIsDesc() ? SortOrder.DESC : SortOrder.ASC);
                }
            }
        }
        return searchBuilder;
    }

    public BoolQueryBuilder getNoOrderQueryCondition() {
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        return getNoOrderQueryCondition(queryBuilder);
    }

    @SuppressWarnings("unchecked")
    public BoolQueryBuilder getNoOrderQueryCondition(BoolQueryBuilder queryBuilder) {
        if (queryBuilder == null) {
            return null;
        }
        /*matchQuery：会将搜索词分词，再与目标查询字段进行匹配，若分词中的任意一个词与目标字段匹配上，则可查询到。待查询的字段类型为text会分词
        
        termQuery：不会对搜索词进行分词处理，而是作为一个整体与目标字段进行匹配，若完全匹配，则可查询到。
        termQuery("key", obj) 完全匹配
        termsQuery("key", obj1, obj2..)   一次匹配多个值
        matchQuery("key", Obj) 单个匹配, field不支持通配符, 前缀具高级特性
        multiMatchQuery("text", "field1", "field2"..);  匹配多个字段, field有通配符忒行
        matchAllQuery();         匹配所有文件*/
        int cndsSize = cnds.size();
        for (MultiCondition multiCnd : cnds) {
            LinkType type = multiCnd.getType();
            BoolQueryBuilder query = queryBuilder;
            if (cndsSize > 1) { // 多组条件
                query = QueryBuilders.boolQuery();

            }
            for (Condition cnd : multiCnd.getConditions()) {
                String colunmName = cnd.getColumn();

                if (cnd.getValues() == null) { // 为空
                    if (cnd.getQueryType() == Condition.Type.EQUAL) {
                        query.mustNot(boost(cnd, QueryBuilders.existsQuery(colunmName))); // 空

                    } else if (cnd.getQueryType() == Condition.Type.NOT_EQUAL) {
                        query.must(boost(cnd, QueryBuilders.existsQuery(colunmName))); // 非空
                    }
                } else {
                    // 每个条件前面加空格，后面不加
                    if (cnd.getQueryType() == Condition.Type.EQUAL) {
                        if ("id".equals(colunmName)) {
                            String otherColumns = cnd.getOtherColumns();
                            query.must(boost(cnd, QueryBuilders.idsQuery().addIds(getMutiKeys(cnd.getValues() + "", otherColumns))));

                        } else {
                            String otherColumns = cnd.getOtherColumns();
                            if (StringUtils.isNotEmpty(otherColumns)) { // 多个值
                                query.must(
                                        boost(cnd, QueryBuilders.termsQuery(colunmName, getMutiKeys(cnd.getValues() + "", otherColumns))));
                            } else {
                                query.must(boost(cnd, QueryBuilders.termQuery(colunmName, cnd.getValues())));
                            }
                        }
                    } else if (cnd.getQueryType() == Condition.Type.NOT_EQUAL) {
                        query.mustNot(QueryBuilders.termQuery(colunmName, cnd.getValues()));
                    } else if (cnd.getQueryType() == Condition.Type.ANALYSIS) { // 分词搜索
                        String otherColumns = cnd.getOtherColumns();
                        if (StringUtils.isNotEmpty(otherColumns)) { // 多字段
                            String[] keys = getMutiKeys(colunmName, otherColumns);
                            Map<String, Float> boostMap = new LinkedHashMap<>();
                            for (int i = 0; i < keys.length; i++) {
                                String key = keys[i];
                                if (key.contains("^")) {
                                    String[] keyArrs = key.split("\\^");
                                    keys[i] = keyArrs[0];
                                    try {
                                        boostMap.put(keyArrs[0], Float.valueOf(keyArrs[1]));
                                    } catch (NumberFormatException e) {
                                        log.error("", e);
                                    }
                                }
                            }
                            MultiMatchQueryBuilder mmqb = QueryBuilders.multiMatchQuery(cnd.getValues(), keys);
                            if (!boostMap.isEmpty()) {
                                for (Map.Entry<String, Float> entry : boostMap.entrySet()) {
                                    mmqb.field(entry.getKey(), entry.getValue());
                                }
                            }
                            query.must(boost(cnd, mmqb)); // 标题、内容

                        } else {
                            query.must(boost(cnd, QueryBuilders.matchQuery(colunmName, cnd.getValues())));
                        }

                    } else if (cnd.getQueryType() == Condition.Type.GT) {
                        query.must(boost(cnd, QueryBuilders.rangeQuery(colunmName).gt(cnd.getValues())));

                    } else if (cnd.getQueryType() == Condition.Type.GE) {
                        query.must(boost(cnd, QueryBuilders.rangeQuery(colunmName).gte(cnd.getValues())));

                    } else if (cnd.getQueryType() == Condition.Type.LT) {
                        query.must(boost(cnd, QueryBuilders.rangeQuery(colunmName).lt(cnd.getValues())));

                    } else if (cnd.getQueryType() == Condition.Type.LE) {
                        query.must(boost(cnd, QueryBuilders.rangeQuery(colunmName).lte(cnd.getValues())));

                    } else if (cnd.getQueryType() == Condition.Type.LIKE || cnd.getQueryType() == Condition.Type.LIKE_LEFT
                            || cnd.getQueryType() == Condition.Type.LIKE_RIGHT) {// TODO 待优化
                        query.must(boost(cnd, QueryBuilders.wildcardQuery(colunmName, cnd.getValues() + "")));

                    } else if (cnd.getQueryType() == Condition.Type.RANGE) {
                        List<Object> list = (List<Object>) cnd.getValues();
                        QueryBuilder rangeQuery = QueryBuilders.rangeQuery(colunmName).gte(list.get(0)).lte(list.get(1));
                        rangeQuery = boost(cnd, rangeQuery);
                        query.must(rangeQuery);

                    } else if (cnd.getQueryType() == Condition.Type.IN_SET) {
                        if ("id".equals(colunmName)) { // id
                            Object[] values = (Object[]) cnd.getValues();
                            int length = values.length;
                            String[] ids = new String[length];
                            for (int i = 0; i < length; i++) {
                                ids[i] = values[i].toString();
                            }
                            query.must(boost(cnd, QueryBuilders.idsQuery().addIds(ids)));
                        } else { // 其他字段查询
                            Object[] values = (Object[]) cnd.getValues();
                            query.must(boost(cnd, QueryBuilders.termsQuery(colunmName, values)));
                        }
                    }
                }

            }

            if (cndsSize > 1) { // 多组条件
                if (type == LinkType.AND) {
                    queryBuilder.must(query);
                } else {
                    queryBuilder.should(query);
                }

            }

        }
        return queryBuilder;
    }

    /**
     * 处理权重
     * 
     * @Title boost
     * @author 吕凯
     * @date 2020年9月17日 下午2:25:32
     * @param cnd
     * @param rangeQuery
     *            void
     */
    private QueryBuilder boost(Condition cnd, QueryBuilder queryBuilder) {
        if (cnd.getBoost() != null) {
            queryBuilder.boost(cnd.getBoost());
        }
        return queryBuilder;
    }

    public BoolQueryBuilder getQueryCondition(SearchSourceBuilder sourceBuilder) {
        BoolQueryBuilder queryBuilder = getNoOrderQueryCondition();
        getOrder(sourceBuilder);
        return queryBuilder;
    }

    public ElasticSearchQueryModel and(MultiCondition multiCon) {
        cnds.add(multiCon);
        multiCon.setType(LinkType.AND);
        return this;
    }

    public ElasticSearchQueryModel or(MultiCondition multiCon) {
        cnds.add(multiCon);
        multiCon.setType(LinkType.OR);
        return this;
    }

    /**
     * 多字段或多值处理,联合查询等用
     * 
     * @Title getMutiKeys
     * @author 吕凯
     * @date 2020年8月12日 下午3:47:16
     * @param keyMain
     * @param keyOthers
     * @return String[]
     */
    private String[] getMutiKeys(String keyMain, String keyOthers) {
        List<String> columnsList = new ArrayList<>();
        columnsList.add(keyMain);
        if (StringUtils.isNotEmpty(keyOthers)) {
            String[] otherColumnsArr = keyOthers.split(",");
            columnsList.addAll(Arrays.asList(otherColumnsArr));
        }
        String[] otherColumnVs = columnsList.toArray(new String[0]);
        return otherColumnVs;
    }

    /**
     * 重写clone方法
     * 
     * @Title clone
     * @author xx
     * @date 2013年7月26日 下午1:46:40
     * @return
     * @throws CloneNotSupportedException
     * @see java.lang.Object#clone()
     */
    @Override
    public Object clone() throws CloneNotSupportedException {

        ElasticSearchQueryModel cloneObj = null;
        try {
            cloneObj = (ElasticSearchQueryModel) super.clone();
            List<MultiCondition> cnds = new ArrayList<>(this.cnds);
            cloneObj.cnds = cnds;
            List<Order> orders = new ArrayList<>(this.orders);
            cloneObj.orders = orders;
        } catch (CloneNotSupportedException e) {
            log.error("", e);
        }
        return cloneObj;
    }

    public static void main(String[] args) {
    }

}
